package com.zlll.winner.service.bbs;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zlll.winner.business.model.bbs.BbsPost;
import com.zlll.winner.business.model.bbs.BbsPostMedia;
import com.zlll.winner.business.service.bbs.IBbsPostMediaService;
import com.zlll.winner.business.service.bbs.IBbsPostService;
import com.zlll.winner.business.vo.bbs.BbsPostVo;
import com.zlll.winner.enums.CommonEnum;
import com.zlll.winner.enums.bbs.PostEnum;
import com.zlll.winner.enums.bbs.PostMediaEnum;
import com.zlll.winner.enums.bbs.SubjectEnum;
import com.zlll.winner.mapper.bbs.BbsPostMapper;
import com.zlll.winner.service.bbs.async.BbsPostAsyncService;
import com.zlll.winner.service.bbs.async.BbsSubjectAsyncService;
import com.zlll.winner.util.HttpClientUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.dubbo.config.annotation.Service;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 论坛频道帖子表 服务实现类
 * </p>
 *
 * @author Walert
 * @since 2019-09-12
 */
@Service
@Slf4j
public class BbsPostServiceImpl extends ServiceImpl<BbsPostMapper, BbsPost> implements IBbsPostService {

    @Autowired
    private IBbsPostMediaService mediaService;

    @Autowired
    private BbsPostAsyncService postAsyncService;

    @Autowired
    private BbsSubjectAsyncService subjectAsyncService;

    @Value("${file.url}")
    private String fileUrl;

    /**
     * 小程序帖子分页列表
     * @param params
     * @return
     */
    public Object fetchPostPageByWeapp(JSONObject params){
        Integer pageNo = params.getInteger("pageNo");
        Integer pageSize = params.getInteger("pageSize");
        IPage<BbsPostVo> page = new Page<>(pageNo, pageSize);
        QueryWrapper<BbsPostVo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("t.is_del",CommonEnum.DelEnum.UNDEL.val());
        queryWrapper.eq("t.audit_status",PostEnum.AuditStatusEnum.PASS.val());
        queryWrapper.eq("t.status",PostEnum.StatusEnum.PUT_AWAY.val());

        Long subjectId = params.getLong("subjectId");
        if(subjectId != null){
            queryWrapper.eq("t.subject_id",subjectId);
        }else{
            queryWrapper.isNull("t.subject_id");
        }

        Integer position = params.getInteger("position");
        if(position != null
                && !position.equals(SubjectEnum.PositionEnum.HOT.val())){
            queryWrapper.eq("t.position", position);
        }else{
            queryWrapper.ne("t.position", 9);
        }

        if(position.equals(SubjectEnum.PositionEnum.CITY.val())){
            String city = params.getString("city");
            queryWrapper.eq("t.city_name",city);
        }
        Long userId = params.getLong("userId");
        if(userId == null){
            userId = -1L;
        } else{
            if(position !=null && position == 9){
                queryWrapper.eq("t.user_id",userId);
            }
        }
        return baseMapper.selectPageByCustomer(page,queryWrapper,userId);
    }

    public List<BbsPostVo> getDetailsList(JSONObject params){
        QueryWrapper<BbsPostVo> queryWrapper = new QueryWrapper<>();
        JSONArray postIds = params.getJSONArray("postIds");
        if(postIds!= null && postIds.size() > 0){
            queryWrapper.in("t.id",postIds);
        }
        Long userId = params.getLong("userId");
        if(userId==null) userId = -1L;
        return baseMapper.getDetailsList(queryWrapper,userId);
    }

    @Override
    public Integer checkUserTodayIssueSum(Long userId){
        Long todayTime = DateUtil.parse(DateUtil.today()).getTime();
        Integer count = baseMapper.selectCount(Wrappers.<BbsPost>lambdaQuery()
                .eq(BbsPost::getIsDel, CommonEnum.DelEnum.UNDEL.val())
                .ge(BbsPost::getIssueTime, todayTime)
                .eq(BbsPost::getUserId, userId)
                .in(BbsPost::getType, PostEnum.TypeEnum.AUDIO.val(), PostEnum.TypeEnum.VIDEO.val()));
        return count;
    }

    /**
     * 论坛帖子分页列表
     *
     * @param params
     * @return
     */
    @Override
    public Object fetchPostPage(JSONObject params) {
        Integer pageNo = params.getInteger("pageNo");
        Integer pageSize = params.getInteger("pageSize");

        IPage<BbsPostVo> page = new Page<>(pageNo, pageSize);
        QueryWrapper<BbsPostVo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("t.is_del",CommonEnum.DelEnum.UNDEL.val());
        Long subjectId = params.getLong("subjectId");
        if(subjectId != null){
            queryWrapper.eq("t.subject_id",subjectId);
        }else{
            queryWrapper.isNull("t.subject_id");
        }
        String position = params.getString("position");
        if(StringUtils.isNotBlank(position)
                && !position.equals(String.valueOf(SubjectEnum.PositionEnum.HOT.val()))){
            queryWrapper.eq("t.position",position);
        }else{
            queryWrapper.ne("t.position", 9);
        }
        String content = params.getString("content");
        if(StringUtils.isNotBlank(content)) {
            queryWrapper.like("t.content", content);
        }
        Integer status = params.getInteger("status");
        if(status != null){
            queryWrapper.eq("t.status",status);
        }
        //新增维权相关条件判断
        Integer complaintStatus = params.getInteger("complaintStatus");
        if(complaintStatus != null){
            queryWrapper.eq("t.complaint_status",complaintStatus);
        }
        Integer auditStatus = params.getInteger("auditStatus");
        if(auditStatus != null){
            queryWrapper.eq("t.audit_status",auditStatus);
        }
        Long beginTime = params.getLong("beginTime");
        Long endTime = params.getLong("endTime");
        if(beginTime != null && endTime != null){
            queryWrapper.between("t.issue_time",beginTime,endTime);
        }
        String userPhone = params.getString("userPhone");
        if(StringUtils.isNotBlank(userPhone)){
            queryWrapper.like("m2.phone",userPhone);
        }
        return baseMapper.selectPageByCustomer(page,queryWrapper,-1L);
    }

    /**
     * 保存贴子
     *
     * @param bbsPost
     * @param params
     * @return
     */
    @Override
    public Object save(BbsPost bbsPost, JSONObject params) throws InterruptedException {
        bbsPost.setIssueTime(System.currentTimeMillis());
        bbsPost.setCreateTime(bbsPost.getIssueTime());
        bbsPost.setUpdateTime(bbsPost.getIssueTime());
        bbsPost.setAuditStatus(PostEnum.AuditStatusEnum.WAIT.val());
        bbsPost.setComplaintStatus(PostEnum.SafeGuardStatusEnum.PASSED.val());
        baseMapper.insert(bbsPost);
        if(bbsPost.getType().equals( PostEnum.TypeEnum.IMAGE.val())){
            JSONArray imageList = params.getJSONArray("imageList");
            List<BbsPostMedia> mediaList = new ArrayList<>();
            imageList.forEach(image->{
                mediaList.add(packingPostMediaData(bbsPost,image.toString(),PostMediaEnum.TypeEnum.IMAGE.val()));
            });
            if(mediaList.size() > 0){
                mediaService.saveOrUpdateBatch(mediaList);
            }
        }else{
            String fileName = params.getString("fileName");
            if(StringUtils.isNotBlank(fileName)){
                mediaService.save(packingPostMediaData(bbsPost,fileName,bbsPost.getType()));
            }
        }
        if(bbsPost.getSubjectId()!=null){
            subjectAsyncService.countPosts(bbsPost.getSubjectId());
        }
        return bbsPost;
    }

    /**
     * 根据ID获取详情
     *
     * @param postId
     * @param userId
     * @return
     */
    @Override
    public BbsPostVo getDetailsById(Long postId,Long userId) {
        if(userId == null) userId = -1L;
        return baseMapper.getDetailsById(postId,userId);
    }

    /**
     * 贴子用户操作统计
     *
     * @param postId
     * @param actionType 1、点赞 2、转发 3、评论
     */
    @Override
    public void userPostActionCount(Long postId, Integer actionType) {
        try {
            postAsyncService.changeNumber(postId,actionType);
            System.out.println("业务处理完成");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 封装贴子媒体对象
     * @param bbsPost
     * @param fileName
     * @param type
     * @return
     */
    private BbsPostMedia packingPostMediaData(BbsPost bbsPost, String fileName,Integer type) {
        BbsPostMedia postMedia = new BbsPostMedia();
        postMedia.setPostId(bbsPost.getId());
        postMedia.setCreateTime(bbsPost.getIssueTime());
        postMedia.setMedia(fileName);
        postMedia.setIsDel(CommonEnum.DelEnum.UNDEL.val());
        postMedia.setMediaType(type);
        return postMedia;
    }

    /**
     * 视频文件临时下载
     * @param netUrl
     * @return
     */
    public File getNetUrlHttp(String netUrl) {
        //对本地文件命名
        String fileName = "tmp.mp4";
        File file = null;
        URL urlFile;
        InputStream inStream = null;
        OutputStream os = null;
        try {
            file = File.createTempFile("tmp", URLEncoder.encode(fileName,"UTF-8"));
            //下载
            urlFile = new URL(netUrl);
            inStream = urlFile.openStream();
            os = new FileOutputStream(file);

            int bytesRead = 0;
            byte[] buffer = new byte[8192];
            while ((bytesRead = inStream.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
        } catch (Exception e) {
            log.error("远程视频获取错误："+ netUrl);
            e.printStackTrace();
        } finally {
            try {
                if (null != os) {
                    os.close();
                }
                if (null != inStream) {
                    inStream.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return file;
    }

    /**
     * 视频截屏
     * @param videoUrl
     * @return
     * @throws Exception
     */
    public  byte[] fetchFrame(String videoUrl) throws Exception {
        long start = System.currentTimeMillis();

        File vFile = getNetUrlHttp(videoUrl);
        FFmpegFrameGrabber ff = new FFmpegFrameGrabber(vFile);
        ff.start();
        int lenght = ff.getLengthInFrames();
        int i = 0;
        Frame f = null;
        while (i < lenght) {
            f = ff.grabFrame();
            if ((i > 5) && (f.image != null)) {
                break;
            }
            i++;
        }

        // 截取的帧图片
        Java2DFrameConverter converter = new Java2DFrameConverter();
        BufferedImage srcImage = converter.getBufferedImage(f);
        int srcImageWidth = srcImage.getWidth();
        int srcImageHeight = srcImage.getHeight();

//        opencv_core.IplImage img = f.image;
//        int owidth = img.width();
//        int oheight = img.height();
        // 对截图进行等比例缩放(缩略图)
        int width = 480;
        int height = (int) (((double) width / srcImageWidth) * srcImageHeight);
        BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
        bi.getGraphics().drawImage(srcImage.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0, 0, null);

        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ImageIO.write(bi, "png", byteArrayOutputStream);
        byte[] bytes = byteArrayOutputStream.toByteArray();

        byteArrayOutputStream.close();
        ff.stop();
        vFile.delete();
        System.out.println(System.currentTimeMillis() - start);
        return bytes;
    }

    /**
     * 获取视频截图imageID
     * @param fileName
     * @return
     */
    public Object getVideoImage(String fileName){
        String resp = null;
        try {
            resp = HttpClientUtil.uploadImage(fileUrl+"/upload",fetchFrame(fileUrl + "file/download" + fileName),"file");
        } catch (Exception e) {
            e.printStackTrace();
        }
        if(StringUtils.isNotBlank(resp)){
            JSONObject respObj = JSONObject.parseObject(resp);
            resp = respObj.getString("fingerprint");
        }
//        String resourcePath = this.getClass().getResource("/").getPath();
//
//        String path = this.getClass().getClassLoader().getResource("ffmpeg.exe").getPath();
//        processImg(fileUrl + "file/download" + fileName,path,resourcePath,"tmp.png",5f);
        return resp;
    }


    public boolean processImg(String veido_path, String ffmpeg_path,String resourcePath, String image_name, float time) {
        File file = getNetUrlHttp(veido_path);
        if (!file.exists()) {
            log.info("路径[" + veido_path + "]对应的视频文件不存在!");
            return false;
        }
        List<String> commands = new ArrayList<String>();
        commands.add(ffmpeg_path);
        commands.add("-ss");//偏移量
        commands.add("2");//这个参数是设置截取视频多少秒时的画面
        commands.add("-i");// 输入
        commands.add(veido_path);
//        commands.add("-y");
        commands.add("-f");//格式化，要输出什么格式的截图
//        commands.add("image2");
        commands.add("mjpeg");
//        commands.add("-t");
//        commands.add("0.001");
//        commands.add("-s"); //-s表示截图的的大小
//        commands.add("960*240"); //这个参数是设置截取图片的大小，但不可任意填写
        commands.add("-vframes");
        commands.add("1");//截取1帧

        commands.add(image_name);
//        System.out.println("savepath===》"+File.separatorChar+"============>"+ffmpeg_path);
//        int lastIndex = ffmpeg_path.lastIndexOf(File.separatorChar);
//        String savePath = ffmpeg_path.substring(0, lastIndex);
//        System.out.println("savepath===》"+savePath);
        try {
            ProcessBuilder builder = new ProcessBuilder();
            builder.directory(new File(resourcePath));//切换工作目录，不加这一句还真不行，此目录为你ffmpeg文件夹的存放目录
            builder.command(commands);
            builder.start();
            System.out.println("截取成功");
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

}
